// 题意：给定大小为n的有限状态集，然后每个状态在m个指令下的转移矩阵（函数）。
//       现在问能不能有个最短的命令序列使得n个状态在经过这个序列后都变成
//       状态0。poj上 n<=8, m<=16
//
// 题解：想了许久。感觉会不会是爆搜。后来有人说这个是NP问题，果断搜了。
//       因为题目数据不会很长，所以就能过了。感觉是需要补充下对NP问题的
//       理解。
//       搜索的时候状态注意不用记录每一位是什么，而是记录某个状态有没有就行。
//
// run: $exec < input
#include <iostream>
#include <queue>

int const maxlen = 1 << 10;
int const maxn = 20;
bool vis[maxlen];
std::string path[maxlen];
int trans[maxn][maxn];
int n, m;

void print(std::string const & s)
{
	if (s == "") { std::cout << "*\n"; return; }
	for (int i = 0; i < (int)s.size(); i++)
		if (s[i] < 10) std::cout << (int)s[i];
		else		   std::cout << char('a' + s[i] - 10);
}

int main()
{
	std::cin >> n >> m;
	for (int i = 0; i < n; i++)
		for (int j = 0; j < m; j++) std::cin >> trans[i][j];

	std::queue<int> q;
	int init = 0;
	for (int i = 0; i < n; i++) init |= 1 << i;
	q.push(init);
	vis[init] = true;
	while (!q.empty()) {
		int now = q.front(); q.pop();
		if (now == 1) break;
		for (int i = 0; i < m; i++) {
			int tmp = 0;
			for (int j = 0; j < n; j++)
				if (now & (1 << j))
					tmp |= 1 << trans[j][i];
			if (!vis[tmp]) {
				vis[tmp] = true;
				path[tmp] = path[now] + char(i);
				q.push(tmp);
			}
		}
	}

	print(path[1]);
}

